package com.sann.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @Aspect 表示该类是一个日志切面
 * @Component注解Spring会把该类对象作为组件注入IOC容器
 */
@Component
@Aspect
public class LogAspect {

    @Pointcut("execution(* com.sann.spring..*.*(..))")
    public void pointcut(){}

    /**
     * 前置通知
     * 外部类可以这样通过全路径切点名来引用
     */
    @Before("com.sann.aspect.LogAspect.pointcut()")
    public void logBefore(JoinPoint joinPoint){
        String method = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("【"+method+"】方法开始执行入参.....："+ Arrays.asList(args));
    }

    /**
     * 返回通知：目标方法正常返回后执行，和异常通知只能有一个会执行（互斥关系）
     */
    @AfterReturning(pointcut = "pointcut()",returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result){
        String method = joinPoint.getSignature().getName();
        System.out.println("【"+method+"】方法执行返回结果......："+result);
    }

    /**
     * 异常通知
     */
    @AfterThrowing(pointcut = "pointcut()", throwing = "ex")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable ex){
        String method = joinPoint.getSignature().getName();
        System.out.println("【"+method+"】方法抛出异常......："+ex);
    }

    /**
     * 最终通知：在目标方法结束后执行，也就是在返回通知或者异常通知后执行。
     */
    @After("pointcut()")
    public void logAfter(JoinPoint joinPoint){
        String method = joinPoint.getSignature().getName();
        System.out.println("【"+method+"】方法执行结束......");
    }
}
